//
//  SWPageManager.swift
//  YiyaPuzzleDemo
//  页面加工厂，检查页面是否有效，根据页面数据生成可打印图片
//  最后要打印时，SWPageManager -> Complete -> SWUploadManager
//  Created by linhan on 16/9/29.
//  Copyright © 2016年 test. All rights reserved.
//

import Foundation
private let _manager:SWPageManager = SWPageManager()
class SWPageManager: NSObject
{
    let processQueue = DispatchQueue(label: "SWPageManager.processQueue", attributes: .concurrent)
    
    private var _launched:Bool = false
    private var _fileManager = FileManager.default
    private var _tasks:[SWGenerationTask] = []
    private var _documentPath:String = ""
    private var _dataPath:String = ""
    private var _addTaskIntervalID:String = ""
    
    private let _queue:OperationQueue = OperationQueue()
    
    class func sharedManager() -> SWPageManager
    {
        return _manager
    }
    
    override init()
    {
        //并行数
        _queue.maxConcurrentOperationCount = 6
    }
    
    func launch()
    {
        if !_launched
        {
            _launched = true
            
            _documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).valueAt(0) ?? ""
            _dataPath = "\(_documentPath)/generationtask.data"
            
            //未完成任务
            pause()
            if let tasks = SWCacheManager.sharedManager().readCache(_dataPath) as? [SWGenerationTask]
            {
                trace("generation tasks:", tasks.count)
                
                for task in tasks
                {
                    addTask(task)
                }
            }//end if tasks
            resume()
            
        }//end _launched
    }
    
    //暂停任务
    func pause()
    {
        _queue.isSuspended = true
    }
    
    //恢复任务
    func resume()
    {
        _queue.isSuspended = false
    }
    
    //提交前进行空白页、空白格检查
    func photoCompletenessCheck(_ book:SWBook, successCallback:@escaping ()->Void, failCallback:@escaping (SWPage)->Void)
    {
        processQueue.async {
            if let pages:[SWPage] = book.pages?.flatMap({$0 as? SWPage})
            {
                for page in pages
                {
                    if !page.completeness
                    {
                        failCallback(page)
                    }
                }
            }
            successCallback()
        }//end queue
    }
    
    //生成所有页面
    private var _batchQueue:OperationQueue = OperationQueue()
    func generationAllPage(_ book:SWBook, successCallback:@escaping ()->Void)
    {
        _batchQueue.maxConcurrentOperationCount = 6
        self._batchQueue.cancelAllOperations()
        processQueue.async {
            if var pages:[SWPage] = book.pages?.flatMap({$0 as? SWPage})
            {
                let t1 = NSDate().timeIntervalSince1970
//                pages += pages //8
//                pages += pages //16
//                pages += pages //32
                //pages += pages //64页
                print("pages:", pages.count)
                var tasks:[SWGenerationTask] = []
                for page in pages
                {
                    if true
                    //if !self.productExists(page, level: .origin)
                    {
                        let task = SWGenerationTask(page: page)
                        if let operation = SWPageGenerateOperation(task: task)
                        {
                            operation.completionBlock = {[weak self] in
                                let operationCount:Int = self?._batchQueue.operationCount ?? 0
                                if operationCount == 0
                                {
                                    successCallback()
                                    trace("总耗时:", NSDate().timeIntervalSince1970 - t1)
                                }
                            }
                            self._batchQueue.addOperation(operation)
                        }
                        //tasks.append(task)
                    }
                }
                
                
            }
        }//end queue
    }
    
    //下载背景小图、大图；合成图小图
    func addTask(_ task:SWGenerationTask, autoStart:Bool = true)
    {
        //过滤无效任务
        guard let page = task.page,
              let largeBgURL = page.largeBgURL,
              let bookID = page.bookID,
              let pageID = page.pageID, bookID != "" && pageID != "" && largeBgURL != "" else{
                return
        }
        
        if autoStart
        {
            pause()
        }
        
        
        //如果队列中未包含此项或者此项未下载完成
        if let index = _tasks.index(where: {($0.page?.bookID ?? "") == bookID && ($0.page?.pageID ?? "") == pageID}),
           let task = _tasks.valueAt(index)
        {
            _tasks[index] = task
        }
        else
        {
            _tasks.append(task)
        }
        
        trace("addGenerationTask:", _tasks.count)
        
        if let operations = _queue.operations as? [SWPageGenerateOperation],
            let index = operations.index(where: {($0.page.bookID ?? "") == bookID && ($0.page.pageID ?? "") == pageID}),
            let operation = operations.valueAt(index)
        {
            operation.update(task)
            trace("任务已在队列中")
        }
        else
        {
            if let operation = SWPageGenerateOperation(task: task)
            {
                addOperation(operation, priority: .normal)
            }
        }
        
        self.save()
        clearTimeout(_addTaskIntervalID)
        if autoStart
        {
            _addTaskIntervalID = setTimeout(5, closure: {[weak self] in
                //TODO
                self?.resume()
            })
        }
        
    }
    
    func addOperation(_ operation:SWPageGenerateOperation, priority:Operation.QueuePriority)
    {
        operation.queuePriority = priority
        operation.successCallback = {[weak self] task in self?.generateFinish(task)}
        
//        if SWDownloadManager.sharedManager().getImage(largeBgURL) == nil
//        {
//            let downloadTask = SWDownloadTask(url: largeBgURL)
//            let downloadOperation = SWDownloadOperation(task: downloadTask)
//            operation.addDependency(downloadOperation)
//            SWDownloadManager.sharedManager().addOperation(downloadOperation, priority:.veryHigh)
//        }
        
        _queue.addOperation(operation)
        trace("_queue.operations:", _queue.operations.count)
    }
    
    //合成图是否存在
    func productExists(_ page:SWPage, level:SWPhotoSizeLevel) -> Bool
    {
        let path = fetchStorePath(page, level:level)
        return _fileManager.fileExists(atPath: path)
    }
    
    //获取原图存储路径
    func fetchStorePath(_ page:SWPage, level:SWPhotoSizeLevel) -> String
    {
        let path = "\(SWBookManager.sharedManager().baseDirectory)/\(fetchRelativePath(page, level:level))"
        return path
    }
    
    //通过相对路径获取绝对路径
    func fetchStorePath(relativePath path:String) -> String
    {
        let path:String = "\(SWBookManager.sharedManager().baseDirectory)/\(path)"
        return path
    }
    
    //获取某个Page相对路径
    func fetchRelativePath(_ page:SWPage, level:SWPhotoSizeLevel) -> String
    {
        let bookID:String = page.bookID ??? "default"
        let pageID:String = page.pageID ??? "default"
        var path:String = "\(bookID)_\(pageID)_\(level.rawValue).jpg"
        if let orderID = page.orderID,orderID != ""
        {
            path = "\(orderID)_\(pageID)_\(level.rawValue).jpg"
        }
        return path
    }
    
    //
    func copyToOrder(_ page:SWPage, orderID:String)
    {
        //_fileManager.copyItem(atPath: <#T##String#>, toPath: <#T##String#>)
    }
    
    private func save()
    {
        SWCacheManager.sharedManager().writeCache(_tasks, path: _dataPath)
    }
    
    private func generateFail()
    {
        //generate()
        //TODO 
        //生成过程中如果失败，应返回具体失败页面
    }
    
    private func generateFinish(_ task:SWGenerationTask)
    {
        //如果需要立即上传，添加到上传队列中
        let uploadRightNow = task.uploadPreviewRightNow
        if let page = task.page, uploadRightNow
        {
            let uploadTask = SWUploadTask(page: page)
            uploadTask.origin = true
            uploadTask.relativePath = SWPageManager.sharedManager().fetchRelativePath(page, level: .preview)
            SWUploadManager.sharedManager().addTask(uploadTask)
        }
        
        //生成完成后从队列中删除
        if let page = task.page,
           let bookID = page.bookID,
           let pageID = page.pageID, bookID != "" && pageID != ""
        {
            if let index = _tasks.index(where: {($0.page?.bookID ?? "") == bookID && ($0.page?.pageID ?? "") == pageID})
            {
                _tasks.removeAtIndexSafely(index)
            }
        }
        
        save()
        
        NotificationCenter.default.post(name:NotificationName.GenerationTaskComplete, object: nil, userInfo: ["task":task])
        
        if _tasks.count == 0
        {
            NotificationCenter.default.post(name: NotificationName.GenerationTaskAllComplete, object: nil)
        }
    }
    
}

